home *** CD-ROM | disk | FTP | other *** search
- /* Timer routines for REND386; written by Dave Stampe, July 1992 */
-
- /* Completely rewritten 19/12/93, to use JOYTIMER.ASM and new, more
- robust control interface, and millisecond timing */
-
- /*
- This code is part of the VR-386 project, created by Dave Stampe.
- VR-386 is a desendent of REND386, created by Dave Stampe and
- Bernie Roehl. Almost all the code has been rewritten by Dave
- Stampre for VR-386.
-
- Copyright (c) 1994 by Dave Stampe:
- May be freely used to write software for release into the public domain
- or for educational use; all commercial endeavours MUST contact Dave Stampe
- (dstampe@psych.toronto.edu) for permission to incorporate any part of
- this software or source code into their products! Usually there is no
- charge for under 50-100 items for low-cost or shareware products, and terms
- are reasonable. Any royalties are used for development, so equipment is
- often acceptable payment.
-
- ATTRIBUTION: If you use any part of this source code or the libraries
- in your projects, you must give attribution to VR-386 and Dave Stampe,
- and any other authors in your documentation, source code, and at startup
- of your program. Let's keep the freeware ball rolling!
-
- DEVELOPMENT: VR-386 is a effort to develop the process started by
- REND386, improving programmer access by rewriting the code and supplying
- a standard API. If you write improvements, add new functions rather
- than rewriting current functions. This will make it possible to
- include you improved code in the next API release. YOU can help advance
- VR-386. Comments on the API are welcome.
-
- CONTACT: dstampe@psych.toronto.edu
- */
-
-
- #include <dos.h>
- #include <bios.h>
- #include <stdio.h>
- #include <conio.h>
- #include <stdlib.h>
- #include <signal.h>
-
- #include "pcdevice.h"
- #include "devpriv.h"
-
- /******************* TIMER INTERRUPT STUFF ****************/
- #define SYNC_INTERVAL 5
-
- int get_ticks_per_second(void)
- {
- return 1000; // always in msec now, so this is not too useful
- }
-
- void tdelay(long d) // delay in msec: current_time() always in msec now
- {
- long dl = current_time() + d;
-
- while(current_time()<=dl);
- }
-
- static long last_render_duration = 200;
- static long render_start_time = 0;
-
- // call before rendering begins
- void register_render_start()
- {
- render_start_time = current_time();
- }
-
- // call after rendering ends
- void register_render_end()
- {
- last_render_duration = current_time() - render_start_time;
- if (last_render_duration < 2) last_render_duration = 2;
- }
-
- // returns time of last render in milliseconds
- long last_render_time()
- {
- return last_render_duration;
- }
-
-
-
- /************* INTERRUPT SETUP?RESET **************/
-
- #define TIMER_VECT 8 /* timer chip int. vector */
- #define KBRD_VECT 9 /* keyboard intercept */
-
- // this is the most portable (PM or DOS) method to chain with
- #define UNUSED_TVECTOR 0x78 /* for timer chain */
- #define UNUSED_KVECTOR 0x79 /* for keyboard chain */
-
-
- void (__interrupt __far *old_kbrd_hook) () = NULL; //DOS keyboard interrupt handler
-
- void (__interrupt __far *old_timer_hook)() = NULL; //DOS 18.2 Hz interrupt handler
-
-
- static void _reset_timer() /* RESET PC TO NORMAL */
- {
- _disable();
-
- if(old_timer_hook)
- setvect(TIMER_VECT, old_timer_hook); /* reset vector */
- old_timer_hook = NULL;
-
- if(old_kbrd_hook)
- setvect(KBRD_VECT, old_kbrd_hook); /* reset vector */
- old_kbrd_hook = NULL;
-
- write_timer(0);
- _enable();
-
- signal(SIGINT, SIG_DFL);
- signal(SIGABRT, SIG_DFL);
- signal(SIGFPE, SIG_DFL);
- }
-
-
- static void _init_timer(int speed) /* SET UP FAST TIMER */
- {
- atexit(_reset_timer); /* set traps for error, ctrl c, */
- signal(SIGABRT, _reset_timer);
- signal(SIGFPE, _reset_timer);
- signal(SIGINT, _reset_timer);
-
- write_timer(speed);
- counts_per_tick = speed;
- timer_tick_count = 0;
- ticks_per_second = 1190000L/speed;
- frame_resync_interval = SYNC_INTERVAL;
-
- /* setup int's if required(first run) */
- if (old_timer_hook==NULL)
- {
- _disable();
- old_timer_hook = getvect(TIMER_VECT); /* setup ISR vectors */
- setvect(UNUSED_TVECTOR, old_timer_hook);
- setvect(TIMER_VECT, timer_isr);
- _enable();
- }
- }
-
- int keymon_on = 0;
-
- int init_key_monitor()
- {
- if (old_kbrd_hook==NULL)
- {
- _disable();
- old_kbrd_hook = getvect(KBRD_VECT); /* setup ISR vectors */
- setvect(UNUSED_KVECTOR,old_kbrd_hook);
- setvect(KBRD_VECT, kbrd_isr);
- _enable();
- keymon_on++;
- return 1;
- }
- return 0;
- }
-
-
- /************** SETUP EXTERNALLY *************/
-
- static unsigned timer_rate = 6000; // default time goal for POWERGLOVE
- static unsigned frame_setup = 0; // can't set timer if frame lock
-
- int init_timer(unsigned speed, void (*timer_hook)())
- {
- if(timer_hook)
- timer_interrupt_hook = timer_hook; // timer tick interrupt handler
- if(frame_setup) return counts_per_tick; // can't set if frame locked!
- if(speed) timer_rate = speed;
-
- _init_timer(timer_rate);
- return counts_per_tick;
- }
-
-
- #define ADVANCE 100 /* time (microseconds) of advance */
- /* in vert. interrupt. Will act as */
- /* "vertical hold" adjustment */
-
-
- int init_frame_lock(unsigned speed, void (*frame_hook)())
- {
- unsigned i_rate;
- unsigned tpf;
-
- frame_interrupt_hook = frame_hook; // frame-end interrupt handler
- if(speed) timer_rate = speed; // suggested speed
- frame_setup++; // lock time base
-
- i_rate = find_vsync_count() - ADVANCE; /* use a multiple of video rate */
- tpf = i_rate/timer_rate; /* about 2x for 72 fps, 3x for 60 */
- if (tpf < 2) tpf = 2; /* need at leas twice for switch */
- if (tpf > 10) tpf = 10; /* come on now... */
- i_rate /= tpf;
- timer_frame_interval = tpf;
-
- _init_timer(i_rate);
- return counts_per_tick;
- }
-
-
-